#pragma once
#include "Common.hpp"
#include "Socket.hpp"
#include "Channel.hpp"
#include "Loop.hpp"

class Acceptor{
private:   
    using AcceptCallback = std::function<void(int)>;

    // 监听套接字读事件回调处理函数 -- 获取新连接, 调用 _accept_callback 函数进行新连接处理
    void HandleRead(){
        int newfd = _listen_socket.Accept();
        if(newfd < 0) return;
        if(_accept_callback) _accept_callback(newfd); // 调用新连接的回调函数
    }
    int CreateServer(int port){
        bool ret = _listen_socket.CreateServer(port);
        assert(ret == true);
        return _listen_socket.Fd();
    }

public:
    // 注意: 这里不能把启动读事件监控放到构造函数中, 必须设置回调函数后, 再去启动
    // 否则有可能造成启动监控后, 立即有事件, 处理的时候回调函数还未设置, 新连接得不到处理, 且资源泄漏
    Acceptor(EventLoop* loop, int port): _listen_socket(CreateServer(port)), _loop(loop), _channel(loop, _listen_socket.Fd()){
        _channel.SetReadCallback(std::bind(&Acceptor::HandleRead, this));
    }
    void SetAcceptCallback(const AcceptCallback &cb){_accept_callback = cb;}
    // 启动监听套接字的监听, 并设置监听套接字的读事件回调函数
    void Listen(){_channel.EnableRead();}

private:
    Socket _listen_socket; // 监听套接字
    EventLoop *_loop;      // 所属的 EventLoop
    Channel _channel;      // 监听套接字对应的 Channel
    AcceptCallback _accept_callback; // 监听套接字的回调函数
};